1 Introducción

En este curso se van a abordar los principales usos de dos de las librerías de R más utilizadas para manipular y formatear datos (dplyr) y realizar figuras (ggplot2) mediante ejemplos sencillos, aumentando la dificultad y las funciones que aprenderéis a utilizar. A continuación se mostrarán algunas de las figuras complejas que sabrás realizar cuando termines este curso.

(Poner algunas figuras complejas: 1) volcano plot)

Para llevar a cabo este curso necesitarás utilizar las siguientes librerías:

library(dplyr) ## Work with dataframes
library(ggplot2) ## Making figures
library(DT) ## Interface tables
library(pasilla) #Bioconductor
library(reshape2) ## Transform data
library(tidyr) ## pivot functions
library(tibble) ## modern dataframes
library(ggrepel) ## geom text without overlap
library(ggpubr) ## Publication-ready ggplot themes

2 La sinergia dplyr-ggplot2

ggplot2 nos permite crear una gran diversidad de gráficos con una capacidad de personalización muy alta.

La creación de gráficos con ggplot2 funciona por capas, siendo esenciales 3 de ellas:

  • data: un data frame que contiene los datos a representar, con todas las variables necesarias.
  • aesthetics o aes: en esta capa se determina qué columna del data frame contiene los valores x e y y aquellas variables que van a determinar aspectos como el color (color), relleno (fill) o la transparencia (alpha).
  • geom: las capas geom_ determinan el tipo de gráfico. Entre ellos, los tipos más frecuentes en bioinformática son:
    • Puntos (geom_point(), geom_jitter())
    • Líneas (geom_line())
    • Barras (geom_bar())
    • Boxplots (geom_boxplot())
    • Heatmaps (geom_tile())

Opcionalmente, distinguimos 3 capas adicionales que ayudan a personalizar un gráfico:

  • facet: sirve para repetir el mismo gráfico para varias condiciones (por ejemplo, para obtener un boxplot de expresión de sanos vs. enfermos por cada gen del dataset)
  • scale: en estas capas se personalizan los ejes x e y (título, límites, número de marcas…) y también se determina la paleta de colores.
  • theme: personalizar la apariencia general del gráfico (tamaño y tipo de fuente, posición de la leyenda…)

Vamos a ver un ejemplo de gráfico sencillo donde se usan todas estas capas. En este gráfico, cada punto representa la expresión de un gen en un paciente:

example_data_tidy %>% # Data
  ggplot(aes(x = State, # Column containing x variable
             y = Expression, # Column containing y variable
             color = State)) + # Column color variable
  
  geom_boxplot() + # Plot boxplot
  geom_jitter(width = 0.1, alpha = 0.5, size = 1) + # Plot dots over the boxplot
  
  facet_wrap(~Gene) + # One plot per gene
  
  scale_x_discrete(name = "Patient status") + # Change x axis title
  scale_y_continuous(name = "Gene expression") + # Change y axis title
  scale_color_brewer(palette = "Set1") + # Change color palette
  
  theme_pubr() + # Publication-ready theme
  theme(axis.text = element_text(size = 10), # Change axis titles font size
        legend.position = "none") # Hide color legend

Estamos representando 3 variables:

  • Estado del paciente (sano o enfermo): representado en el eje x y en el color.
  • Expresión génica: representado en el eje y.
  • Gen: se genera un panel por cada gen.

Por ello, necesitamos un data frame con la siguiente estructura, donde las tres variables mencionadas anteriormente tienen una columna propia y cada fila es una observación:

example_data_tidy %>% datatable()

Sin embargo, los datos de partida suelen tener una estructura más parecida a esta, donde los datos de expresión y la información de los pacientes vienen en tablas separadas (metadatos y datos):

  • Metadatos: tabla que contiene información de los pacientes. En este caso, nos interesa la columna State.
example_metadata %>% datatable()
  • Datos: tabla que contiene los datos de expresión génica, donde cada fila es un paciente y cada columna un gen.
example_data %>% datatable()

Aquí entra en juego el preprocesamiento de datos con dplyr para transformar y combinar estas tablas:

En este tutorial vamos a ver distintas funciones para transformar tablas de datos con dplyr y cómo podemos ponerlas en un formato adecuado para ggplot2, así como generar gráficos de alta calidad con este paquete.

3 Paquete dplyr

En la mayoría de los casos, los datos que vamos a utilizar no suelen estar en el formato que nos interesa para utilizar ggplot2. Por ello se requieren de otras librerías que nos faciliten este trabajo de transformación de datos. La librería más potente para esto es dplyr.

3.1 Funciones básicas de dplyr

(TO-DO: Explicar los pipes)

Esta librería tiene múltiples funcionalidades. Para hacer un análisis exploratorio de alguna de las más importantes, se usará una tabla con información clínica de muestras de sangre de lupus y donantes sanos.

# Leemos el fichero
datos_clinicos = read.delim("https://bioinformaticsgrx.es/wp-content/uploads/2020/02/Phenodata.txt")

# Hacemos algún cambio rápido
datos_clinicos[datos_clinicos$Neutrophil_percent == 0,"Neutrophil_percent"] <- NA
datos_clinicos[datos_clinicos$Lymphocyte_percent == 0,"Lymphocyte_percent"] <- NA
datatable(datos_clinicos)

3.1.1 select -> Filtrar columnas

(TO-DO: Cambiar nombres de columnas con select)

## select: 
# La fórmula %>% se utiliza para introducir el dataframe
datatable(datos_clinicos %>% select(Patient,State,Gender)) 
# También podemos poner la primera y última columna que queremos mantener
# usando la fórmula from:to
datatable(datos_clinicos %>% select(Patient:Race)) 
 # Y podemos combinar ambas técnicas
datatable(datos_clinicos %>% select(Patient:Gender,Treatment))
# También podemos eliminar columnas
datatable(datos_clinicos %>% select(-State))

3.1.2 filter -> Filtrar filas en base a condiciones

# Indicamos la condición que queremos
datatable(datos_clinicos %>% filter(State == "Healthy")) 
# Pudiendo añadir varias
datatable(datos_clinicos %>% filter(State == "Healthy" & Gender == "F")) 
# O complicando el filtrado como queramos
datatable(datos_clinicos %>% filter((State == "SLE" & Gender == "F") & (Neutrophil_percent > 50 | Lymphocyte_percent > 30))) 
# Igualmente podemos añadir otras funciones con %>%
datatable(datos_clinicos %>% filter((State == "SLE" & Gender == "F") & (Neutrophil_percent > 50 | Lymphocyte_percent > 30)) %>% select(Patient)) 

3.1.3 mutate -> Crear una nueva columna

# Podemos generar una nueva columna llamada NLR que sea resultado de dividir
# las variables Neutrophil_percent y Lymphocyte_percent
datatable(datos_clinicos %>% mutate(NLR = Neutrophil_percent / Lymphocyte_percent))
# Como para algunas muestras no tendremos datos de NLR, podemos fitrar las mismas
# como se ha explicado previamente
datatable(datos_clinicos %>% mutate(NLR = Neutrophil_percent / Lymphocyte_percent) %>% filter(!(is.na(NLR))))
# Una función especial es add_rownames, que permite convertir los nombres de las filas en una columna más
datatable(datos_clinicos %>% add_rownames("Samples"))
## Warning: `add_rownames()` is deprecated as of dplyr 1.0.0.
## Please use `tibble::rownames_to_column()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.

3.1.4 pull -> Crear un vector desde un dataframe

# Solo indicar la columna que se quiere convertir en vector
datos_clinicos %>% pull(Patient)
##   [1] BAY-H377  BAY-H290  BAY-H303  BAY-H380  BAY-H306  BAY-H248  BAY-H304 
##   [8] BAY-H288  BAY-H305  BAY-H373  BAY-H243  BAY-H257  BAY-H276  BAY-H294 
##  [15] BAY-H217  BAY-H379  BAY-H281  BAY-H287  BAY-H275  BAY-H246  BAY-H285 
##  [22] BAY-H384  BAY-H277  BAY-H241  BAY-H218  BAY-H269  BAY-H217  BAY-H218 
##  [29] BAY-H288  BAY-H248  BAY-H306  BAY-H294  BAY-H303  BAY-H243  BAY-H1169
##  [36] BAY-H079  BAY-H297  BAY-H276  BAY-H200  BAY-H284  BAY-H305  SLE-161  
##  [43] SLE-144   SLE-80    SLE-197   SLE-254   SLE-73    SLE-161   SLE-169  
##  [50] SLE-260   SLE-233   SLE-233   SLE-80    SLE-202   SLE-202   SLE-31   
##  [57] SLE-31    SLE-60    SLE-260   SLE-83    SLE-224   SLE-234   SLE-194  
##  [64] SLE-169   SLE-237   SLE-231   SLE-169   SLE-60    SLE-179   SLE-244  
##  [71] SLE-138   SLE-60    SLE-169   SLE-241   SLE-254   SLE-202   SLE-60   
##  [78] SLE-143   SLE-237   SLE-202   SLE-125   SLE-59    SLE-169   SLE-224  
##  [85] SLE-179   SLE-90    SLE-179   SLE-60    SLE-254   SLE-144   SLE-179  
##  [92] SLE-244   SLE-233   SLE-138   SLE-169   SLE-90    SLE-144   SLE-244  
##  [99] SLE-233   SLE-144   SLE-169   SLE-254   SLE-256   SLE-80    SLE-31   
## [106] SLE-80    SLE-254   SLE-224   SLE-279   SLE-60    SLE-233   SLE-73   
## [113] SLE-256   SLE-80    SLE-202   SLE-234   SLE-264   SLE-152   SLE-60   
## [120] SLE-214   SLE-256   SLE-60    SLE-197   SLE-202   SLE-31    SLE-202  
## [127] SLE-234   SLE-237   SLE-171   SLE-202   SLE-143   SLE-224   SLE-197  
## [134] SLE-138   SLE-59    SLE-260   SLE-179   SLE-233   SLE-233   SLE-202  
## [141] SLE-224   SLE-179   SLE-169   SLE-169   SLE-80    SLE-110   SLE-254  
## [148] SLE-244   SLE-233   SLE-202   SLE-202   SLE-152   SLE-60    SLE-271  
## [155] SLE-254   SLE-241   SLE-125   SLE-169   SLE-31    SLE-161   SLE-244  
## [162] SLE-125   SLE-171   SLE-110   SLE-169   SLE-234   SLE-202   SLE-296  
## [169] SLE-90    SLE-264   SLE-125   SLE-125   SLE-254   SLE-231   SLE-171  
## [176] SLE-60    SLE-202   SLE-80    SLE-144   SLE-169   SLE-110   SLE-191  
## [183] SLE-158   SLE-125   SLE-260   SLE-80    SLE-264   SLE-110   SLE-144  
## [190] SLE-179   SLE-202   SLE-152   SLE-202   SLE-169   SLE-231   SLE-244  
## [197] SLE-144   SLE-143   SLE-138   SLE-60    SLE-169   SLE-241   SLE-256  
## [204] SLE-169   SLE-144   SLE-110   SLE-171   SLE-80    SLE-231   SLE-80   
## [211] SLE-256   SLE-152   SLE-197   SLE-110   SLE-179   SLE-80    SLE-231  
## [218] SLE-287   SLE-169   SLE-144   SLE-80    SLE-31    SLE-144   SLE-254  
## [225] SLE-171   SLE-158   SLE-179   SLE-202   SLE-158   SLE-231   SLE-169  
## [232] SLE-80    SLE-224   SLE-234   SLE-271   SLE-244   SLE-224   SLE-191  
## [239] SLE-179   SLE-241   SLE-144   SLE-161   SLE-260   SLE-31    SLE-234  
## [246] SLE-271   SLE-59    SLE-234   SLE-224   SLE-90    SLE-244   SLE-179  
## [253] SLE-202   SLE-271   SLE-143   SLE-158   SLE-125   SLE-264   SLE-31   
## [260] SLE-202   SLE-90    SLE-169   SLE-254   SLE-260   SLE-80    SLE-256  
## [267] SLE-244   SLE-171   SLE-202   SLE-144   SLE-264   SLE-110   SLE-237  
## [274] SLE-241   SLE-233   SLE-171   SLE-244   SLE-197   SLE-80    SLE-31   
## [281] SLE-125   SLE-60    SLE-169   SLE-158   SLE-31    SLE-231   SLE-60   
## [288] SLE-169   SLE-194   SLE-114   SLE-60    SLE-169   SLE-138   SLE-152  
## [295] SLE-80    SLE-144   SLE-271   SLE-202   SLE-144   SLE-143   SLE-31   
## [302] SLE-241   SLE-254   SLE-179   SLE-80    SLE-169   SLE-209   SLE-307  
## [309] SLE-339   SLE-343   SLE-327   SLE-325   SLE-326   SLE-339   SLE-327  
## [316] SLE-324   SLE-324   SLE-339   SLE-327   SLE-325   SLE-325   SLE-339  
## [323] SLE-342   SLE-326   SLE-327   SLE-324   SLE-343   SLE-311   SLE-324  
## [330] SLE-326   SLE-325   SLE-312   SLE-324   SLE-327   SLE-326   SLE-335  
## [337] SLE-325   SLE-324   SLE-339   SLE-311   SLE-327   SLE-325   SLE-311  
## [344] SLE-325   SLE-324   SLE-325   SLE-344   BAY-H241  BAY-H288  BAY-H273 
## [351] BAY-H285  BAY-H162  BAY-H275  BAY-H222  BAY-H287  BAY-H246  BAY-H282 
## [358] BAY-H281  BAY-H277  BAY-H384  BAY-H235  BAY-H206  BAY-H164  BAY-H230 
## [365] BAY-H379  BAY-H380  BAY-H377  BAY-H304  BAY-H254  BAY-H134  BAY-H160 
## [372] BAY-H255  BAY-H231  BAY-H199  BAY-H257  BAY-H290  BAY-H344  BAY-H373 
## [379] SLE-34    SLE-87    SLE-129   SLE-192   SLE-172   SLE-189   SLE-99   
## [386] SLE-155   SLE-168   SLE-212   SLE-192   SLE-79    SLE-121   SLE-242  
## [393] SLE-184   SLE-40    SLE-168   SLE-95    SLE-155   SLE-40    SLE-170  
## [400] SLE-188   SLE-79    SLE-218   SLE-170   SLE-242   SLE-99    SLE-230  
## [407] SLE-20    SLE-216   SLE-213   SLE-225   SLE-200   SLE-181   SLE-155  
## [414] SLE-121   SLE-163   SLE-172   SLE-225   SLE-78    SLE-18    SLE-175  
## [421] SLE-128   SLE-128   SLE-121   SLE-180   SLE-210   SLE-40    SLE-172  
## [428] SLE-207   SLE-34    SLE-19    SLE-249   SLE-172   SLE-78    SLE-133  
## [435] SLE-147   SLE-242   SLE-281   SLE-175   SLE-79    SLE-188   SLE-201  
## [442] SLE-225   SLE-213   SLE-199   SLE-201   SLE-55    SLE-78    SLE-199  
## [449] SLE-252   SLE-245   SLE-155   SLE-218   SLE-136   SLE-123   SLE-268  
## [456] SLE-213   SLE-267   SLE-210   SLE-175   SLE-211   SLE-255   SLE-79   
## [463] SLE-245   SLE-184   SLE-187   SLE-141   SLE-212   SLE-200   SLE-170  
## [470] SLE-133   SLE-175   SLE-133   SLE-182   SLE-218   SLE-155   SLE-212  
## [477] SLE-200   SLE-40    SLE-222   SLE-178   SLE-121   SLE-255   SLE-175  
## [484] SLE-34    SLE-189   SLE-192   SLE-78    SLE-200   SLE-65    SLE-225  
## [491] SLE-183   SLE-55    SLE-176   SLE-249   SLE-225   SLE-166   SLE-34   
## [498] SLE-40    SLE-175   SLE-199   SLE-201   SLE-65    SLE-177   SLE-95   
## [505] SLE-160   SLE-178   SLE-225   SLE-123   SLE-225   SLE-65    SLE-142  
## [512] SLE-20    SLE-147   SLE-182   SLE-155   SLE-19    SLE-188   SLE-170  
## [519] SLE-207   SLE-182   SLE-150   SLE-55    SLE-210   SLE-181   SLE-211  
## [526] SLE-65    SLE-252   SLE-78    SLE-133   SLE-141   SLE-201   SLE-180  
## [533] SLE-180   SLE-175   SLE-150   SLE-78    SLE-55    SLE-188   SLE-95   
## [540] SLE-128   SLE-192   SLE-189   SLE-166   SLE-216   SLE-78    SLE-199  
## [547] SLE-157   SLE-79    SLE-78    SLE-142   SLE-180   SLE-229   SLE-141  
## [554] SLE-212   SLE-177   SLE-121   SLE-175   SLE-121   SLE-123   SLE-190  
## [561] SLE-129   SLE-40    SLE-199   SLE-266   SLE-163   SLE-128   SLE-192  
## [568] SLE-65    SLE-154   SLE-184   SLE-79    SLE-242   SLE-21    SLE-212  
## [575] SLE-189   SLE-184   SLE-141   SLE-183   SLE-79    SLE-121   SLE-157  
## [582] SLE-65    SLE-141   SLE-218   SLE-34    SLE-65    SLE-293   SLE-212  
## [589] SLE-242   SLE-155   SLE-121   SLE-99    SLE-65    SLE-225   SLE-121  
## [596] SLE-189   SLE-168   SLE-176   SLE-55    SLE-79    SLE-183   SLE-225  
## [603] SLE-181   SLE-242   SLE-178   SLE-268   SLE-266   SLE-78    SLE-121  
## [610] SLE-188   SLE-163   SLE-189   SLE-78    SLE-99    SLE-183   SLE-163  
## [617] SLE-181   SLE-65    SLE-105   SLE-65    SLE-19    SLE-189   SLE-212  
## [624] SLE-225   SLE-181   SLE-200   SLE-121   SLE-133   SLE-200   SLE-78   
## [631] SLE-170   SLE-172   SLE-201   SLE-212   SLE-178   SLE-123   SLE-178  
## [638] SLE-141   SLE-213   SLE-180   SLE-40    SLE-21    SLE-201   SLE-182  
## [645] SLE-141   SLE-182   SLE-40    SLE-128   SLE-95    SLE-225   SLE-183  
## [652] SLE-170   SLE-200   SLE-34    SLE-211   SLE-172   SLE-188   SLE-189  
## [659] SLE-79    SLE-134   SLE-281   SLE-163   SLE-181   SLE-182   SLE-177  
## [666] SLE-213   SLE-155   SLE-245   SLE-199   SLE-78    SLE-79    SLE-183  
## [673] SLE-252   SLE-218   SLE-176   SLE-219   SLE-34    SLE-190   SLE-154  
## [680] SLE-79    SLE-163   SLE-182   SLE-184   SLE-183   SLE-230   SLE-55   
## [687] SLE-136   SLE-133   SLE-121   SLE-184   SLE-199   SLE-141   SLE-218  
## [694] SLE-21    SLE-79    SLE-95    SLE-182   SLE-87    SLE-34    SLE-175  
## [701] SLE-134   SLE-183   SLE-176   SLE-121   SLE-163   SLE-180   SLE-79   
## [708] SLE-172   SLE-170   SLE-65    SLE-163   SLE-188   SLE-176   SLE-155  
## [715] SLE-141   SLE-65    SLE-40    SLE-155   SLE-55    SLE-199   SLE-199  
## [722] SLE-225   SLE-181   SLE-79    SLE-181   SLE-199   SLE-225   SLE-141  
## [729] SLE-175   SLE-142   SLE-189   SLE-34    SLE-34    SLE-168   SLE-206  
## [736] SLE-176   SLE-123   SLE-219   SLE-199   SLE-133   SLE-216   SLE-216  
## [743] SLE-188   SLE-65    SLE-105   SLE-199   SLE-172   SLE-166   SLE-211  
## [750] SLE-176   SLE-78    SLE-189   SLE-267   SLE-95    SLE-242   SLE-78   
## [757] SLE-213   SLE-55    SLE-176   SLE-79    SLE-245   SLE-55    SLE-55   
## [764] SLE-121   SLE-182   SLE-95    SLE-188   SLE-99    SLE-230   SLE-177  
## [771] SLE-21    SLE-150   SLE-105   SLE-225   SLE-154   SLE-213   SLE-206  
## [778] SLE-150   SLE-293   SLE-183   SLE-55    SLE-176   SLE-252   SLE-172  
## [785] SLE-176   SLE-201   SLE-219   SLE-172   SLE-218   SLE-172   SLE-242  
## [792] SLE-89    SLE-210   SLE-219   SLE-199   SLE-210   SLE-155   SLE-40   
## [799] SLE-187   SLE-99    SLE-129   SLE-178   SLE-40    SLE-267   SLE-199  
## [806] SLE-281   SLE-150   SLE-168   SLE-192   SLE-136   SLE-21    SLE-189  
## [813] SLE-189   SLE-166   SLE-20    SLE-229   SLE-213   SLE-129   SLE-218  
## [820] SLE-163   SLE-200   SLE-79    SLE-79    SLE-210   SLE-55    SLE-255  
## [827] SLE-20    SLE-200   SLE-155   SLE-170   SLE-155   SLE-20    SLE-128  
## [834] SLE-200   SLE-229   SLE-245   SLE-79    SLE-269   SLE-99    SLE-132  
## [841] SLE-147   SLE-40    SLE-199   SLE-121   SLE-172   SLE-175   SLE-170  
## [848] SLE-267   SLE-188   SLE-172   SLE-87    SLE-199   SLE-277   SLE-99   
## [855] SLE-79    SLE-34    SLE-201   SLE-188   SLE-123   SLE-242   SLE-178  
## [862] SLE-157   SLE-78    SLE-154   SLE-199   SLE-105   SLE-136   SLE-187  
## [869] SLE-128   SLE-281   SLE-129   SLE-55    SLE-34    SLE-79    SLE-281  
## [876] SLE-141   SLE-34    SLE-79    SLE-121   SLE-105   SLE-155   SLE-211  
## [883] SLE-78    SLE-181   SLE-123   SLE-201   SLE-166   SLE-176   SLE-129  
## [890] SLE-129   SLE-172   SLE-132   SLE-189   SLE-128   SLE-178   SLE-40   
## [897] SLE-40    SLE-213   SLE-20    SLE-201   SLE-199   SLE-200   SLE-141  
## [904] SLE-199   SLE-170   SLE-252   SLE-172   SLE-78    SLE-176   SLE-230  
## [911] SLE-183   SLE-225   SLE-201   SLE-189   SLE-172   SLE-268   SLE-212  
## [918] SLE-189   SLE-319   SLE-308   SLE-313   SLE-336   SLE-328   SLE-331  
## [925] SLE-304   SLE-316   SLE-320   SLE-341   SLE-346   SLE-321   SLE-328  
## [932] SLE-323   SLE-331   SLE-337   SLE-352   SLE-321   SLE-333   SLE-341  
## [939] SLE-304   SLE-331   SLE-321   SLE-316   SLE-321   SLE-348   SLE-347  
## [946] SLE-305   SLE-323   SLE-348   SLE-304   SLE-304   SLE-317   SLE-308  
## [953] SLE-331   SLE-338   SLE-332   SLE-331   SLE-313   SLE-308   SLE-350  
## [960] SLE-336   SLE-308   SLE-347   SLE-304   SLE-304   SLE-304   SLE-316  
## [967] SLE-313   SLE-308   SLE-337   SLE-331   SLE-332   SLE-333   SLE-337  
## [974] SLE-313   SLE-349   SLE-322   SLE-345   SLE-346   SLE-308   SLE-334  
## [981] SLE-333   SLE-304   SLE-340   SLE-313   SLE-319   SLE-340   SLE-340  
## [988] SLE-337   SLE-341   SLE-321   SLE-321   SLE-321   SLE-323   SLE-334  
## [995] SLE-321   SLE-313  
## 204 Levels: BAY-H079 BAY-H1169 BAY-H134 BAY-H160 BAY-H162 BAY-H164 ... SLE-99

3.1.5 group_by -> Agrupar en base a una condición

# Esta función por si sola no produce ningún cambio, sino que se utiliza para
# indicar a funciones posteriores que todo lo que se haga se hará
# separarando los diferentes grupos de la variable que se indique
datatable(datos_clinicos %>% group_by(Gender))

3.1.6 summarize -> Estadísiticas de los datos

#Queremos saber la media de SLEDAI de las muestras
datos_clinicos %>% summarize(Mean_SLEDAI = mean(SLEDAI,na.rm = T))
##   Mean_SLEDAI
## 1    5.940763
# Como se ha indicado previamente, podemos agrupar los datos usando la función group_by
datos_clinicos %>% group_by(Gender) %>% summarize(Mean_SLEDAI = mean(SLEDAI,na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 2 x 2
##   Gender Mean_SLEDAI
##   <fct>        <dbl>
## 1 F             6.05
## 2 M             5.14
datos_clinicos %>% group_by(State) %>% summarize(Max_SLEDAI = max(SLEDAI,na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 2 x 2
##   State   Max_SLEDAI
##   <fct>        <int>
## 1 Healthy          0
## 2 SLE             35
datos_clinicos %>% group_by(Race) %>% summarize(SD_SLEDAI = sd(SLEDAI,na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 4 x 2
##   Race  SD_SLEDAI
##   <fct>     <dbl>
## 1 AA         6.97
## 2 AS         0   
## 3 C          4.50
## 4 H          5.09

3.1.7 arrange -> Ordenar una columna

# De menor a mayor
datatable(datos_clinicos %>% arrange(SLEDAI))
# De mayor a menor
datatable(datos_clinicos %>% arrange(desc(SLEDAI)))
# O estableciendo el orden manualmente
datatable(datos_clinicos %>% arrange(factor(Gender, levels = c("M","F"))))

3.1.8 count -> Contar el número de filas de cada factor de una columna

# Podemos ver cuantas filas hay de cada State
datos_clinicos %>% count(State)
##     State   n
## 1 Healthy  72
## 2     SLE 924
# Y agrupar por Gender
datos_clinicos %>% group_by(Gender) %>% count(State)
## # A tibble: 4 x 3
## # Groups:   Gender [2]
##   Gender State       n
##   <fct>  <fct>   <int>
## 1 F      Healthy    57
## 2 F      SLE       817
## 3 M      Healthy    15
## 4 M      SLE       107

3.1.9 Pipes Complejos

A continuación harmeos un pipe más complejo de los vistos hasta ahora, para ver el potencial que podemos sacarle a dplyr.

datos_clinicos %>% 
  # Creamos la columna NLR
  mutate(NLR = Neutrophil_percent / Lymphocyte_percent) %>% 
  # Filtramos para quedarnos solo con lupus y sin NA en NLR
  filter(!(is.na(NLR)) & State == "SLE") %>% 
  # Agrupamos por paciente. Cada paciente tiene una o varias visitas
  group_by(Patient) %>% 
  # Quedándonos con los pacientes con más de 3 visitas
  filter(n() > 3) %>% 
  # Y vemos cuantas visitas de cada paciente están por debajo o por encima de los valores normales de NLR
  count(NLR < 0.78 | NLR > 3.53) 
## # A tibble: 150 x 3
## # Groups:   Patient [83]
##    Patient `NLR < 0.78 | NLR > 3.53`     n
##    <fct>   <lgl>                     <int>
##  1 SLE-105 FALSE                         5
##  2 SLE-110 FALSE                         5
##  3 SLE-110 TRUE                          2
##  4 SLE-121 FALSE                        10
##  5 SLE-121 TRUE                          5
##  6 SLE-123 FALSE                         6
##  7 SLE-123 TRUE                          1
##  8 SLE-125 FALSE                         8
##  9 SLE-128 FALSE                         4
## 10 SLE-128 TRUE                          4
## # … with 140 more rows

3.2 Pivotar tablas (TO-DO)

3.3 Combinar tablas

dplyr también nos da la posibilidad de combinar varias tablas de forma similar a como se hacen consultas en bases de datos. Para mostrar estas funciones seguiremos usando la base de datos clínicos de pacientes de lupus. La otra tabla que vamos a usar es una tabla de expresión de genes ficticia, con el fin de que no sea muy costoso computacionalmente

# Añadir los rownames como columna llamada Samples
datos_clinicos <- datos_clinicos %>% add_rownames("Samples")

#Quedarnos con las 6 primeras muestras de lupus con NLR válido
muestras_lupus = datos_clinicos %>% 
  mutate(NLR = Neutrophil_percent / Lymphocyte_percent) %>%
  filter(!(is.na(NLR)) & State == "SLE") %>% 
  select(Samples) %>%
  head() %>%
  pull()

#Quedarnos con las 6 primeras muestras de sanos
muestras_sano = datos_clinicos %>% 
  filter(State == "Healthy") %>% 
  select(Samples) %>%
  head() %>%
  pull()


# Crear la tabla
gene_expression = data.frame(Genes = rep(paste0("Gene",seq(1,10)), c(rep(12,10))),
                             Samples = rep(c(muestras_lupus,muestras_sano),10),
                             Values = rnorm(120))

datatable(gene_expression)

Las funciones principales para combinar dataframes son: inner_join, left_join / right_join, full_join

## Inner join: MATCH IN BOTH TABLES
datatable(gene_expression %>% inner_join(datos_clinicos,by="Samples"))
## Left join: prioritizes left table
datatable(gene_expression %>% left_join(datos_clinicos,by="Samples"))
datatable(datos_clinicos %>% left_join(gene_expression,by="Samples"))
datatable(gene_expression %>% right_join(datos_clinicos,by="Samples"))
datatable(datos_clinicos %>% right_join(gene_expression,by="Samples"))
datatable(gene_expression %>% full_join(datos_clinicos,by="Samples"))

(TO-DO: Join por columnas con distinto nombre)

3.4 Caso práctico

A continuación vamos a preparar la tabla que vamos a usar para generar los gráficos en ggplot2. Para ello seguiremos usando los datos clínicos y las 12 muestras elegidas previamente, pero en este caso vamos a utilizar los datos reales de expresión de genes. Para evitar que nos lleve mucho tiempo, hemos preparado una matriz de expresión de 1000 genes

# Descargar la matriz de expresión
exp_data = read.delim("https://bioinformaticsgrx.es/wp-content/uploads/2022/03/expr.txt")
dim(exp_data)
## [1] 1000  996
# Para pasar la matriz a un formato que nos sirva para ggplot2 usamos la librería reshape2
# y dplyr
gene_expression = as.data.frame(exp_data) %>% 
  rownames_to_column(var = "Genes") %>%  
  pivot_longer(cols = datos_clinicos$Samples,names_to = "Samples",values_to = "Values") %>%
  filter(Samples %in% c(muestras_lupus,muestras_sano)) %>%
  inner_join(datos_clinicos,by="Samples")
datatable(gene_expression)
## Warning in instance$preRenderHook(instance): It seems your data is too big
## for client-side DataTables. You may consider server-side processing: https://
## rstudio.github.io/DT/server.html

4 Paquete ggplot2

# Generar un diagrama de cajas (boxplot)
ggplot(data = gene_expression,aes(x=Samples,y=Values))+ # Con la función ggplot indicamos el dataframe que queremos usar, así como las columnas que se quieren usar en los ejes x e y
  geom_boxplot() # La función geom_boxplot se usa para generar el diagrama de cajas

# Si en vez de un diagrama de cajas quisiéramos generar un gráfico de tipo violín, solo cambiamos la función geom_boxplot por geom_violin
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()

Como es lógico, estas figuras no quedan bien. Por ejemplo, los nombres de las muestras se sobrelapan, el color del fondo puede no gustarnos etc. Para modificar los aspectos estéticos de las figuras usaremos la función theme.

4.1 theme -> Modificar la apariencia

(TO-DO: Hablar de ggpubr)

En primer lugar vamos a comentar las diferentes temáticas que existen por defecto en ggplot2. Como se verá a continuación, cada temática cambia varios elementos del gráfico como el color de fondo o el color de los ejes

ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme_classic()

ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme_bw()

ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme_dark()

ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme_light()

ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme_minimal()

Sin embargo en la mayoría de los casos querremos establecer nuestro propio diseño. Si miramos la ayuda de la función theme, veremos muchísimos parámetros que podemos modificar.

Por ejemplo, si queremos cambiar el tamaño del texto lo podemos hacer de así

# Para modificar el texto debemos usar la función element_text
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme(text = element_text(size = 20)) # Para cambiar todo el texto

# Si solo queremos cambiar el texto del título de los ejes usamos el parametro axis.title
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme(axis.title = element_text(size = 20,color = "red")) # También podemos añadir color

# Y si lo que queremos es modificar los valores de los ejes, usamos la función axis.text
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  # usamos axis.text.x para cambiar solo el eje x
  theme(axis.text.x =  element_text(size = 20,color = "red"))

# El propósito de ver todo esto era evitar que los nombres se mezclen.
# Una buena solución es ponerlas en vertical, modificando el ángulo
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  #vjust para alinear el nombre en el centro
  theme(axis.text.x =  element_text(angle = 90,vjust = 0.5))

Igualmente podemos modificar los ejes del gráfico para cambiar el color o quitarlos

# Para modificar ambos usamos la función axis.line con la función element_line
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme(axis.text.x =  element_text(angle = 90,vjust = 0.5),
        axis.line = element_line(colour = "black"))

# Si queremos modificar alguno específicamente, lo indicamos
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme(axis.text.x =  element_text(angle = 90,vjust = 0.5),
        axis.line.x = element_line(colour = "blue"))

Y finalmente podemos cambiar el fondo de la gráfica

# Para modificar el fondo, usamos el parámetro panel.background con la función element_rect
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme(axis.text.x =  element_text(angle = 90,vjust = 0.5),
        axis.line = element_line(colour = "black"),
        panel.background = element_rect(fill = "blue"))

# Si queremos controlar las rejillar usamos los parámetros panel.grid.major y panel.grid.minor
# con la función element_line
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme(axis.text.x =  element_text(angle = 90,vjust = 0.5),
        axis.line = element_line(colour = "black"),
        panel.background = element_rect(fill = "white"),
        panel.grid.major = element_line(colour = "purple"),
        panel.grid.minor = element_line(colour = "orange"))

# Si no queremos que ningo de estos elementos aparezca
# usamos la función element_blank

ggplot(data = gene_expression,aes(x=Samples,y=Values))+
  geom_violin()+
  theme(axis.text.x =  element_text(angle = 90,vjust = 0.5),
        axis.line = element_line(colour = "black"),
        panel.background = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank())

Por supuesto, con la cantidad de parámetros que se incluyen en la función theme hay muchas más cosas que se pueden modificar. Algunos de ellos los veremos en las siguientes secciones, principalmente aquellas relacionadas con la leyenda.

5 Session info

sessionInfo()
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1
## 
## locale:
##  [1] LC_CTYPE=en_GB.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=es_ES.UTF-8        LC_COLLATE=en_GB.UTF-8    
##  [5] LC_MONETARY=es_ES.UTF-8    LC_MESSAGES=en_GB.UTF-8   
##  [7] LC_PAPER=es_ES.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=es_ES.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] ggpubr_0.2.5   magrittr_1.5   ggrepel_0.8.2  tibble_3.0.0   tidyr_1.0.2   
##  [6] reshape2_1.4.3 pasilla_1.14.0 DT_0.13        ggplot2_3.3.5  dplyr_1.0.2   
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.0.4           RColorBrewer_1.1-2   pillar_1.4.3        
##  [4] compiler_3.6.3       plyr_1.8.6           tools_3.6.3         
##  [7] digest_0.6.26        jsonlite_1.7.1       evaluate_0.14       
## [10] lifecycle_0.2.0      gtable_0.3.0         pkgconfig_2.0.3     
## [13] rlang_1.0.0          cli_3.1.1            rstudioapi_0.11     
## [16] crosstalk_1.1.0.1    yaml_2.2.1           xfun_0.23           
## [19] withr_2.1.2          stringr_1.4.0        knitr_1.28          
## [22] generics_0.0.2       vctrs_0.3.8          htmlwidgets_1.5.1   
## [25] grid_3.6.3           tidyselect_1.1.0     glue_1.6.1          
## [28] R6_2.4.1             fansi_0.4.1          rmarkdown_2.5.3     
## [31] farver_2.0.3         purrr_0.3.3          scales_1.1.0        
## [34] ellipsis_0.3.2       htmltools_0.5.0.9001 colorspace_1.4-1    
## [37] ggsignif_0.6.0       labeling_0.3         utf8_1.1.4          
## [40] stringi_1.4.6        munsell_0.5.0        crayon_1.3.4